<?php
/**
 * --------------------------------------------------------------------
 * MCore精简框架
 * 作者：阿枫，QQ：52037872，Email：support@mdeve.com
 * --------------------------------------------------------------------
 *
 * SVN revision information:
 * @version $Revision: 1 $:
 * @author  $Author: zy $:
 * @date      $Date: 2017-03-10 21:12:21 +0800 (星期五, 10 三月 2017) $:
 */

class _TemplateClass extends __basic_def {

    /////////////////////////////////////////////////////////////////////////////////
    // 配置区域，因涉及到正规表达式，勿改。

    // 循环定义区域 {# ... #}
    private $delimiter_regular = '/{#(.+?)#}/s';

    // 在模板中引用模板 {! ... !}
    private $filltemplate_regular = '/{!(.+?)!}/s';

    // php代码定义区域，可以在模板中插入PHP代码，但PHP代码会优先执行。{? ... ?}，非必要不要这样做！
    private $phpcode_regular = '/{\?(.+?)\?}/s';
    /////////////////////////////////////////////////////////////////////////////////

    public $current_template = "";
    protected $templatesCaches = array();	// 模板缓存数组

    // 从模板文件加载
    function load($template_name){
        $this->current_template = $template_name;
        $this->templatesCaches[$template_name] = $this->get_template_content($template_name);

        // 替换常量
        $this->templatesCaches[$template_name] = str_replace(
            array("{MANAGE_PATH}", "{DATA_PATH}", "{CORE_PATH}", "{UPLOAD_PATH}"),
            array(MANAGE_PATH, DATA_PATH, CORE_PATH, UPLOAD_PATH),
            $this->templatesCaches[$template_name]);

        $this->_adjust($template_name);
    }

    // 处理加载的模板
    private function _adjust($template_name){
        // 填充模板 {! xxx !}
        if(preg_match_all($this->filltemplate_regular , $this->templatesCaches[$template_name] , $matches)){
            foreach($matches[1] as $t){
                // 如果不存在此模板则加载
                if(!array_key_exists($t, $this->templatesCaches)){	// 如果不存在此模板则加载
                    $template_cache = $this->get_template_content($t);
                    $this->templatesCaches[$t] = $template_cache;
                } else {
                    $template_cache = $this->templatesCaches[$t];
                }
                $this->templatesCaches[$this->current_template] = str_replace("{!{$t}!}", $template_cache, $this->templatesCaches[$this->current_template]);
                $this->_adjust($t);
            }
        }

        // 处理模板中的PHP代码 {? .. ?}
        if(preg_match_all($this->phpcode_regular , $this->templatesCaches[$this->current_template] , $matches)){
            foreach($matches[1] as $code){
                eval($code);
            }
        }
        $this->templatesCaches[$this->current_template] = preg_replace($this->phpcode_regular , '' , $this->templatesCaches[$this->current_template]);
    }

    // 从文件获取模板内容
    private function get_template_content($template_name){
        $f = "{$template_name}.tpl";
        if(!file_exists("{$f}")) {
            exit("Template {$template_name} not found!");
        }
        return file_get_contents($f);
    }

    // 获取模板内容
    function get($template_name) {
        $this->load($template_name);
        return $this->templatesCaches[$template_name];
    }

    /**
     * 解析准备处理的模板
     * @param string $name 模板名称
     */
    public function parse($name){
        $this->current_template = $name;
    }

    // 显示模板
    function display($return_content = false) {
        // 如果有调试信息则输出调试
        if (_TRACE) {
            $this->templatesCaches[$this->current_template] = str_replace ( "</body>", $this->getBacktrace () . "</body>", $this->templatesCaches[$this->current_template] );
        }
        if($return_content) {
            return $this->templatesCaches[$this->current_template];
        } else {
            echo $this->templatesCaches[$this->current_template];
        }
    }





    /**
     * 替换模板中的内容
     * @param string $mark 模板中的标记
     * @param string $val 替换成的内容
     */
    public function set_var($mark, $val){
        if($this->current_template == "") exit("Please parse template first!");
        $this->templatesCaches[$this->current_template] = str_replace($mark , $val , $this->templatesCaches[$this->current_template]);
    }

    /**
     * 批量替换模板中的变量
     * @param array $array
     * @param boolean 是否自动在key添加标签 {}
     */
    public function set_vars($array, $use_tag = true){
        if($this->current_template == "") exit("Please parse template first!");
        foreach($array as $key=>$val){
            if(is_array($val)) continue;
            if($use_tag) {
                $this->templatesCaches[$this->current_template] = str_replace("{{$key}}", $val, $this->templatesCaches[$this->current_template]);
            } else {
                $this->templatesCaches[$this->current_template] = str_replace("{$key}", $val, $this->templatesCaches[$this->current_template]);
            }
        }
    }

    /**
     * 在模板前面添加html内容
     * @param $html HTML string
     */
    public function insert_html($html) {
        if($this->current_template == "") exit("Please parse template first!");
        $this->templatesCaches[$this->current_template] = $html . $this->templatesCaches[$this->current_template];
    }


    /**
     * 获取模板中的循环区域，如有多个区域，只取第一个。
     * @param 循环区域名称 $block
     * @param bool $clear_tag 获取标签内容后是否删除标签名，用来从模板中直接提取内容
     * @return string|boolean
     */
    function get_block($block, $clear_tag=false){
        if($this->current_template == "") exit("Please parse template first!");
        $d_regular = str_replace("(", "{$block}(", $this->delimiter_regular);
        if(preg_match_all($d_regular , $this->templatesCaches[$this->current_template] , $matches)){
            $this->templatesCaches[$this->current_template] = str_replace($matches[0][0], ($clear_tag ? "" : "{". $block. "}" ), $this->templatesCaches[$this->current_template]);
            return $matches[1][0];
        }
        return false;
    }

    /**
     * 处理模板中的循环区域，模板中的 {xxx} 会由数组中的数据自动替换
     * @param string $block_name 循环区域名称
     * @param array $array 传入的参数，二维数组
     * @param int $separate_num 隔多少行增加1个空格分隔栏，对<tr>循环无效！！！
     */
    function process_block($block_name, $array, $separate_num=0){
        if($this->current_template == "") exit("Please parse template first!");
        if(!strlen($block_name)) halt("Parameter error");
        $box = $this->get_block($block_name);
        $list = "";
        $i = 1;
        if(is_array($array)) {
            foreach ($array as $r) {
                $t = $box;
                foreach ($r as $key => $val) {
                    $t = str_replace("{" . $key . "}", $val, $t);
                }
                $list .= $t;
                if ($separate_num) {
                    if ($i % $separate_num == 0) $list .= "<br>";
                }
                $i++;
            }
        }
        $this->set_var("{". $block_name. "}", $list);
    }


    // 显示页面运行信息
    function getBacktrace($ignore = 2){
        global $config;
        $trace = "<br /><br /><div class=\"clear debug\"><strong>[页面TRACE信息]</strong><div class=\"trace\"><p>";
        $load_files = get_included_files();
        $trace .= "当前页面：". $_SERVER["REQUEST_URI"]. "<br />";
        $trace .= "请求方法：". $_SERVER["REQUEST_METHOD"]. "<br />";
        $trace .= "请求时间：". date("Y-m-d H:i:s", $_SERVER["REQUEST_TIME"]). "<br />";
        $trace .= "通讯协议：". $_SERVER["SERVER_PROTOCOL"]. "<br />";
        $trace .= "用户代理：". $_SERVER["HTTP_USER_AGENT"]. "<br />";
        $trace .= "运行内存：" . number_format(memory_get_usage() - $GLOBALS['_startUseMems']). " Bytes<br />";
        $trace .= "运行时间：". (time() + microtime() - $GLOBALS['_beginTime']). " 秒<br />";
        $trace .= "<br /><strong>[加载模板：" . sizeof($this->templatesCaches) . "]</strong><br />";
        foreach($this->templatesCaches as $key => $file){
            $trace .= "[{$key}.tpl]<br />";
        }
        $trace .= "<br /><strong>[加载文件：" . sizeof($load_files) . "]</strong><br />";
        foreach($load_files as $key => $file){
            $file = substr($file, strlen($config["INSTALL_PATH"]));
            $trace .= "[{$key}] => {$file}<br />";
        }
        $trace .= "<br /><strong>[TRACE信息]</strong><br />";
        foreach (debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS) as $k => $v) {
            if ($k < $ignore) {
                continue;
            }
            $trace .= '#' . ($k - $ignore) . ' ' . $v['file'] . '(' . $v['line'] . '): ' . (isset($v['class']) ? $v['class'] . '->' : '') . $v['function'] . '(';
            $trace .= isset($v['args']) ? implode(', ', $v['args']) : "";
            $trace .= ')' . "<br />";
        }
        $trace .= "</p></div></div>";
        return $trace;
    }


    /**
     * 压缩html : 清除换行符,清除制表符,去掉注释标记
     * @param $string
     * @return 压缩后的$string
     * */
    function compress_html($string) {
        $string = str_replace("\r\n", '', $string); //清除换行符
        $string = str_replace("\n", '', $string); //清除换行符
        $string = str_replace("\t", '', $string); //清除制表符
        $pattern = array (
            "/> *([^ ]*) *</", //去掉注释标记
            '/[\s]+/',
            "/\" /",
            "/ \"/",
            '/\*[^*]*\*/'
        );
        $replace = array (
            ">\\1<",
            " ",
            "\"",
            "\"",
            ""
        );
        return preg_replace($pattern, $replace, $string);
    }

    /**
     * 设置网页 title
     * @param string $val
     */
    public function set_title($val){
        if($this->current_template == "") exit("Please parse template first!");
        if(preg_match_all('/<head>(.+?)<\/head>/s' , $this->templatesCaches[$this->current_template] , $matches)){
            if(sizeof($matches[1])){
                // 如果找到了title段，直接修改
                if(preg_match_all('/<title>(.+?)<\/title>/s' , $this->templatesCaches[$this->current_template] , $matches1)){
                    foreach($matches1[0] as $b){
                        $this->templatesCaches[$this->current_template] = str_replace($b, "<title>{$val}</title>", $this->templatesCaches[$this->current_template]);
                    }
                }else{	// 没有找到title段，增加title段
                    // 查找现有的meta，在第一个meta后面增加title段
                    if(preg_match_all('/<meta(.+?)\">/s' , $this->templatesCaches[$this->current_template] , $matches2)){
                        $meta = $matches2[0][0] ."\r\n<title>{$val}</title>";
                        $this->templatesCaches[$this->current_template] = str_replace($matches2[0][0], $meta, $this->templatesCaches[$this->current_template]);
                    }
                }
            }
        }else{	// 没有找到head段，不做操作。

        }
    }

}